import * as THREE from "../../three/build/three.module.js";
import {OrbitControls} from "../../three/examples/jsm/controls/OrbitControls.js";
import {MapControls} from "../../three/examples/jsm/controls/MapControls.js";
import {DragControls} from "../../three/examples/jsm/controls/DragControls.js";
import {TransformControls} from "../../three/examples/jsm/controls/TransformControls.js";

let scene, camera, renderer, raycaster;
let areaDatas=[];
window.areaDatas = areaDatas;
class AreaData{
    
    adcode;name;center;centroid;childrenNum;level;subFeatureIndex;acroutes;parent;

    mesh;
    lineMesh;

    isSelected = false;
    isMouseHover = false;

    constructor(properties){
        this.adcode = properties.adcode;
        this.name = properties.name;
        this.center = properties.center;
        this.centroid = properties.centroid;
        this.childrenNum = properties.childrenNum;
        this.level = properties.level;
        this.subFeatureIndex = properties.subFeatureIndex;
        this.acroutes = properties.acroutes;
        this.parent = properties.parent;
    }
    set IsSelected( val ){
        this.isSelected = val;
        this.updateMaterial();
    }
    get IsSelected(){
        return this.isSelected;
    }
    set IsMouseHover( val ){
        this.isMouseHover = val;
        this.updateMaterial();
    }
    get IsMouseHover(){
        return this.isMouseHover;
    }
    setMesh(mesh, lineMesh){
        this.mesh = mesh;
        this.lineMesh = lineMesh;
        mesh.data = this;
    }
    setMaterial(material){
        this.mesh.children.map(function(mesh){
            mesh.material = material;
        })
    }

    updateMaterial(){
        if( this.isMouseHover &&  this.isSelected) {this.setMaterial(MyMap.materialSelected_And_MouseHover); return;}
        if( this.isMouseHover && !this.isSelected) {this.setMaterial(MyMap.materialMouseHover); return;}
        if(!this.isMouseHover &&  this.isSelected) {this.setMaterial(MyMap.materialSelected); return;}
        if(!this.isMouseHover && !this.isSelected) {this.setMaterial(MyMap.materialDefault); return;}
    }
}
class MyMap{
    static materialDefault = new THREE.MeshBasicMaterial({color:0xcc0000});
    static materialMouseHover = new THREE.MeshBasicMaterial({color:0xcc8866});
    static materialSelected = new THREE.MeshBasicMaterial({color:0x008800});
    static materialSelected_And_MouseHover = new THREE.MeshBasicMaterial({color:0x668866});
    static materialLine = new THREE.LineBasicMaterial({
        color:0xffff00,
        // transparent: 0.5,
        // depthWrite: false,
        // polygonOffset: true,
        // polygonOffsetFactor: -4,
        // polygonOffsetUnits: 100,
        });

    static areaDatas = areaDatas;
    static areaDataMouseHover = null;

    static MouseHover(areaData){
        if(this.areaDataMouseHover == areaData) return;
        if(this.areaDataMouseHover)
            this.areaDataMouseHover.IsMouseHover = false;
        areaData.IsMouseHover = true;
        this.areaDataMouseHover = areaData;
    }
}

init();
animate();


function init(){

    initThree();
    initCamera();
    initScene();
    testScene();
    initRay();

    function initThree(){
        scene = new THREE.Scene();
        camera = new THREE.PerspectiveCamera(50, window.innerWidth/ window.innerHeight, 0.1, 1000);
        renderer = new THREE.WebGLRenderer({ antialias: true, logarithmicDepthBuffer: true });
        camera.position.z = 150;

        camera.rotation.x = -Math.PI/2;

        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        // new DragControls([scene],camera, renderer.domElement);
        camera.updateMatrix();
        // updateMatrix();
        let control = new MapControls(camera, renderer.domElement);
        window.control = control;
        control.minPolarAngle = 0;
        control.maxPolarAngle = 0.1;

        window.scene = scene;
        window.camera = camera;
        window.renderer = renderer;
    }

    function initCamera(){
        camera.position.set(122,5,-31);
        control.target.set(122,0,-31);
        control.update();
    }

    function initScene(){
        initMexico();
        initShangHai();

    }

    function initShangHai(){

        $.getJSON("./上海市.json", function (data) {
            let shanghaiMesh = new THREE.Group();

            for(let featureI=0; featureI<data.features.length; featureI++){ // 每个区 featureI featureIndex
                let feature = data.features[featureI];
                let areaData = new AreaData(feature.properties);

                areaDatas[areaData.name] = areaData;
                areaData.setMesh(new THREE.Group(), new THREE.Group());
                shanghaiMesh.add(areaData.mesh, areaData.lineMesh);

                for(let shapeI=0; shapeI<feature.geometry.coordinates.length; shapeI++){ // 每个连续的,不分离的形状
                    let shapeData = feature.geometry.coordinates[shapeI];

                    for(let carveI=0; carveI<shapeData.length; carveI++){ // 每个子午线切割后的形状

                        let carveData = shapeData[carveI];
                        let shape = new THREE.Shape();
                        shape.moveTo(...carveData[carveData.length-1]);

                        for(let i=0; i< carveData.length; i++){ // 每个坐标
                            shape.lineTo(...carveData[i]);
                        }

                        areaData.mesh.add(createShape(shape));
                        areaData.lineMesh.add(createLine(shape));

                    }

                }
                    
            }

            let shanghaiBox = new THREE.Group();
            shanghaiBox.add(shanghaiMesh);
            shanghaiBox.rotation.x = -Math.PI/2;
            // shanghaiBox.position.set(-121, -31);

            scene.add(shanghaiBox);
        });    

    }

    function createShape(shape){
        let geometry = new THREE.ShapeGeometry(shape);
        let material = MyMap.materialDefault;
        let mesh = new THREE.Mesh(geometry, material);
        return mesh;
    }

    function createLine(shape){
        shape.autoClose = true;
        var points = shape.getPoints();
        var geometryPoints = new THREE.BufferGeometry().setFromPoints( points );
        var line = new THREE.Line( geometryPoints, MyMap.materialLine );
        line.position.z = 0.0001;
        return line;
    }

    function initMexico(){
        let data = [ [ [ -97.140008307670712, 25.869997463478398 ], [ -97.702945522842242, 24.272343044526735 ], [ -97.699043952204192, 21.898689480064263 ], [ -95.900884975959968, 18.82802419684873 ], [ -94.839063483442715, 18.562717393462208 ], [ -94.425729539756219, 18.144370835843347 ], [ -91.407903408559264, 18.87608327888023 ], [ -90.771869879910867, 19.284120388256781 ], [ -90.278618333684904, 20.999855454995554 ], [ -88.543866339862859, 21.49367544197662 ], [ -86.811982388032959, 21.331514797444754 ], [ -87.62105445021075, 19.646553046135921 ], [ -87.436750454441778, 19.472403469312269 ], [ -87.837191128271513, 18.25981598558343 ], [ -88.490122850279306, 18.48683055264172 ], [ -88.848343878926585, 17.883198147040332 ], [ -91.001519945015957, 17.817594916245696 ], [ -91.002269253284169, 17.254657701074279 ], [ -91.453921271515128, 17.252177232324186 ], [ -90.438866950222007, 16.410109768128109 ], [ -90.464472622422647, 16.069562079324726 ], [ -91.747960171255954, 16.066564846251765 ], [ -92.229248623406306, 15.251446641495875 ], [ -92.227750006869826, 14.538828640190957 ], [ -93.875168830118525, 15.940164292865916 ], [ -94.691656460330137, 16.200975246642884 ], [ -96.557434048228288, 15.653515122942792 ], [ -100.82949886758132, 17.17107107184205 ], [ -101.91852800170022, 17.916090196193977 ], [ -103.50098954955808, 18.292294623278849 ], [ -104.9920096504755, 19.316133938061682 ], [ -105.73139604370766, 20.434101874264115 ], [ -105.39777299683135, 20.531718654863425 ], [ -105.26581722697404, 21.422103583252351 ], [ -106.02871639689897, 22.773752346278627 ], [ -108.40190487347098, 25.172313951105934 ], [ -109.26019873740665, 25.580609442644061 ], [ -109.29164384645628, 26.442934068298428 ], [ -110.39173173708571, 27.16211497650454 ], [ -110.64101884646163, 27.859876003525528 ], [ -111.17891883018785, 27.94124054616907 ], [ -112.2282346260904, 28.954408677683489 ], [ -113.14866939985717, 31.170965887978923 ], [ -114.77645117883503, 31.79953217216115 ], [ -114.67389929895177, 30.162681179315996 ], [ -111.61648902061921, 26.662817287700477 ], [ -110.65504899782889, 24.298594672131117 ], [ -110.17285620811344, 24.265547593680424 ], [ -109.40910437705571, 23.364672349536249 ], [ -110.03139197471444, 22.823077500901206 ], [ -110.29507097048366, 23.430973212166691 ], [ -112.18203589562148, 24.738412787367167 ], [ -112.3007108223797, 26.012004299416617 ], [ -115.05514217818501, 27.722726752222911 ], [ -114.57036556685495, 27.741485297144891 ], [ -114.16201839888464, 28.566111965442303 ], [ -115.51865393762699, 29.556361599235402 ], [ -117.12776, 32.53534 ], [ -114.72139, 32.72083 ], [ -114.815, 32.52528 ], [ -111.02361, 31.33472 ], [ -108.24194, 31.34222 ], [ -108.24, 31.754853718166373 ], [ -106.50759, 31.75452 ], [ -105.03737, 30.64402 ], [ -104.45697, 29.57196 ], [ -103.94, 29.27 ], [ -103.11, 28.97 ], [ -102.48, 29.76 ], [ -101.6624, 29.7793 ], [ -100.9576, 29.380710000000136 ], [ -99.52, 27.54 ], [ -99.02, 26.37 ], [ -97.140008307670712, 25.869997463478398 ] ] ] [0];

        let shape = new THREE.Shape();
        shape.moveTo(...data[data.length-1]);
        for(let i=0; i< data.length; i++){
            shape.lineTo(...data[i]);
        }
        let geometry = new THREE.ShapeGeometry(shape);
        let material = new THREE.MeshBasicMaterial({color: 0xff0000, side: THREE.DoubleSide});
        let mesh = new THREE.Mesh(geometry, material);

        scene.add(mesh);

        let box = new THREE.BoxHelper( mesh, 0xffff00 );
        scene.add( box );
    }

    function testScene(){
        let mesh = new THREE.Mesh(
            new THREE.BoxBufferGeometry(),
            new THREE.MeshBasicMaterial({color: 0xff0000})
        );
        mesh.position.x=5;
        scene.add(mesh);

        mesh = new THREE.Mesh(
            new THREE.BoxBufferGeometry(),
            new THREE.MeshBasicMaterial({color: 0x00ff00})
        );
        mesh.position.y=5;
        scene.add(mesh);

        mesh = new THREE.Mesh(
            new THREE.BoxBufferGeometry(),
            new THREE.MeshBasicMaterial({color: 0x0000ff})
        );
        mesh.position.z=5;
        scene.add(mesh);
    }

    function initRay(){
        raycaster = new THREE.Raycaster();
        let onClickPosition = new THREE.Vector2();
        let isMouseMoveAfterDown = false;

        renderer.domElement.addEventListener(`mousedown` , function(e){
            let mousePos = new THREE.Vector3();
            if(e.button != 0) return; // 如果不是左击, 直接跳出
            onClickPosition.set(e.offsetX,e.offsetY); // 记录鼠标按下时的坐标
            isMouseMoveAfterDown = false;
        });

        
        renderer.domElement.addEventListener(`mouseup` , function(e){
            let mousePos = new THREE.Vector3();
            if(e.button != 0) return; // 如果不是左击, 直接跳出
            console.log(`e.offset`,e.offsetX, e.offsetY)
            if(isMouseMoveAfterDown == true) return; // 是否移过位置,移动过,跳出
            
            let rendererSize=renderer.getSize();
            mousePos.set(e.offsetX/rendererSize.x-.5, -(e.offsetY/rendererSize.y-.5));
            mousePos.x *= 2;
            mousePos.y *= 2;
            rayLaunch();


            function rayLaunch(){
                let items = [];
                for(let key in areaDatas ){
                    items.push(...areaDatas[key].mesh.children);
                }
                console.log(items);
                
                raycaster.setFromCamera(mousePos, camera);

                let intersection = raycaster.intersectObjects(items);

                if(intersection.length){
                    let areaData = intersection[0].object.parent.data;
                    areaData.IsSelected =! areaData.IsSelected;
                    console.log(`areaData.IsSelected`,areaData.IsSelected);
                }
            }
        });

        renderer.domElement.addEventListener(`mousemove` , function(e){
            let mousePos = new THREE.Vector3();
            isMouseMoveAfterDown = true;
            let rendererSize=renderer.getSize();
            
            mousePos.set(e.offsetX/rendererSize.x-.5, -(e.offsetY/rendererSize.y-.5));
            mousePos.x *= 2;
            mousePos.y *= 2;
            rayLaunch();


            function rayLaunch(){
                let items = [];
                for(let key in areaDatas ){
                    items.push(...areaDatas[key].mesh.children);
                }
                
                raycaster.setFromCamera(mousePos, camera);
                let intersection = raycaster.intersectObjects(items);

                if(intersection.length){
                    let areaData = intersection[0].object.parent.data;
                    MyMap.MouseHover(areaData);
                }
            }
            
        });

    }


}



function animate(){
    requestAnimationFrame(animate);
    // scene.children[0].rotation.z+=0.01;
    renderer.render(scene, camera);
}


